import os
import json
from py2neo import Graph, Node
import cgi, cgitb
import csv

graph = Graph("http://192.168.32.203:7474", username="neo4j", password='xxxx')
graph.delete_all()


class MedicalGraph:
    def __init__(self):
        cur_dir = '/home/iotapp/OneCup'
        self.data_path = os.path.join(cur_dir, 'data/b.json')
        self.g = Graph(
            host='192.168.32.203',  # neo4j 搭载服务器的ip地址，ifconfig可获取到
            http_port=7474,  # neo4j 服务器监听的端口号
            user='neo4j',  # 数据库user name，如果没有更改过，应该是neo4j
            password='xxxxx')

    '''读取文件'''

    def read_nodes(self):
        # 共11类节点
        link_modules = []  # 集群
        servers = []  # 服务器
        errors = []  # 问题
        servers_infos = []  # 服务器信息
        error_infos = []  # 问题信息
        systems = []  # 问题所属系统
        err_classes = []  # 问题所属类别
        err_son_classes = []  # 问题子类
        err_son_classes_knows = []  # 问题子类知识点
        cla_son_infos = []  # 子类信息
        cla_son_know_infos = []  # 子类知识点信息
        # 筛选空节点
        link_modules_ = []  # 集群
        servers_ = []  # 服务器
        errors_ = []  # 问题
        error_infos_ = []  # 问题信息
        servers_infos_ = []  # 服务器信息
        systems_ = []  # 问题所属系统
        err_classes_ = []  # 问题所属类别
        err_son_classes_ = []  # 问题子类
        err_son_classes_knows_ = []  # 问题子类知识点
        cla_son_infos_ = []  # 子类信息
        cla_son_know_infos_ = []  # 子类知识点信息

        # 构建节点实体关系
        rels_server = []  # 问题－服务器关系
        rels_sys_server = []  # 系统-服务器关系
        rels_link_module = []  # 问题－集群关系
        rels_err_class = []  # 问题-类别关系
        rels_cla_error = []  # 类别-问题关系
        rels_err_system = []  # 问题-系统关系
        rels_sys_module = []  # 系统-集群关系
        rels_sys_error = []  # 系统-问题关系
        rels_server_module = []  # 服务器-集群关系
        rels_cla_son_cla = []  # 问题大类-子类关系
        rels_son_cla_konw = []  # 问题子类-子类知识点关系
        count = 0
        with open('/home/iotapp/OneCup/chatbot/upload/1.csv', 'r', encoding='utf-8-sig') as f:
            reader = csv.reader(f)
            fieldnames = next(reader)  # 获取数据的第一列，作为后续要转为字典的键名 生成器，next方法获取
            # print(fieldnames)
            csv_reader = csv.DictReader(f, fieldnames=fieldnames)  # list of keys for the dict 以list的形式存放键名
            count = 0
            for row in csv_reader:
                d = {}
                for k, v in row.items():
                    d[k] = v
                d['link_module'] = d['link_module'].split('；')
                data = json.dumps(d, ensure_ascii=False)
                error_dict = {}
                server_dict = {}
                cla_dict = {}
                son_cla_dict = {}
                know_dict = {}

                count += 1
                #				print(count)
                data_json = json.loads(data)
                error = data_json['name']
                error_dict['name'] = error
                errors_.append(error)
                error_dict['desc'] = ''
                error_dict['err_cause'] = ''
                error_dict['check_way'] = ''
                error_dict['solve_way'] = ''
                error_dict['err_effect'] = ''

                # 服务器相关信息
                server = data_json['server']
                server_dict['server'] = server
                servers_.append(server)
                server_dict['ip_addr'] = ''
                if 'ip_addr' in data_json:
                    server_dict['ip_addr'] = data_json['ip_addr']
                servers_infos_.append(server_dict)
                # 问题大类信息
                err_class = data_json['err_class']
                cla_dict['err_class'] = err_class
                err_classes_.append(err_class)
                # 问题子类信息
                err_son_class = data_json['err_son_class']
                son_cla_dict['err_son_class'] = err_son_class
                err_son_classes_.append(err_son_class)
                son_cla_dict['cla_url'] = ''
                if 'cla_url' in data_json:
                    son_cla_dict['cla_url'] = data_json['cla_url']
                cla_son_infos_.append(son_cla_dict)
                # 子类知识点信息
                err_son_class_know = data_json['son_cla_know']
                know_dict['son_cla_know'] = err_son_class_know
                err_son_classes_knows_.append(err_son_class_know)
                know_dict['son_cla_url'] = ''
                know_dict['know_desc'] = ''
                if 'son_cla_url' in data_json:
                    know_dict['son_cla_url'] = data_json['son_cla_url']
                if 'know_desc' in data_json:
                    know_dict['know_desc'] = data_json['know_desc']
                cla_son_know_infos_.append(know_dict)
                #				print(know_dict)
                # 问题相关信息
                if 'desc' in data_json:
                    error_dict['desc'] = data_json['desc']
                if 'err_cause' in data_json:
                    error_dict['err_cause'] = data_json['err_cause']
                if 'check_way' in data_json:
                    error_dict['check_way'] = data_json['check_way']
                if 'solve_way' in data_json:
                    error_dict['solve_way'] = data_json['solve_way']
                if 'err_effect' in data_json:
                    error_dict['err_effect'] = data_json['err_effect']
                error_infos_.append(error_dict)
                # 系统信息
                system = data_json['system']
                error_dict['system'] = system
                systems_.append(system)
                #				if 'system' in data_json:
                #					error_dict['system'] = data_json['system']
                # 关系字典
                if 'system' in data_json:
                    rels_err_system.append([error, system])
                    rels_sys_error.append([system, error])
                if 'err_class' in data_json:
                    rels_err_class.append([error, err_class])
                    rels_cla_error.append([err_class, error])
                    rels_cla_son_cla.append([err_class, err_son_class])
                if 'err_son_class' in data_json:
                    rels_son_cla_konw.append([err_son_class, err_son_class_know])
                if 'link_module' in data_json:
                    link_module = data_json['link_module']
                    for _link_module in link_module:
                        rels_link_module.append([error, _link_module])
                        rels_sys_module.append([system, _link_module])
                        rels_server_module.append([server, _link_module])
                    link_modules_ += link_module
            # 去掉空值节点
            link_modules = [i for i in link_modules_ if i != '']
            servers = [i for i in servers_ if i != '']
            errors = [i for i in errors_ if i != '']
            systems = [i for i in systems_ if i != '']
            err_classes = [i for i in err_classes_ if i != '']
            err_son_classes = [i for i in err_son_classes_ if i != '']
            err_son_classes_knows = [i for i in err_son_classes_knows_ if i != '']
            error_infos = [i for i in error_infos_ if i['name'] != '']
            servers_infos = [i for i in servers_infos_ if i['ip_addr'] != '']
            cla_son_infos = [i for i in cla_son_infos_ if i['cla_url'] != '']
            cla_son_know_infos = [i for i in cla_son_know_infos_ if i['son_cla_know'] != '']
            print(err_son_classes_knows)
            # 返回节点值
            return set(link_modules), set(servers), set(errors), set(systems), set(err_classes), set(
                err_son_classes), set(
                err_son_classes_knows), error_infos, servers_infos, cla_son_infos, cla_son_know_infos, rels_link_module, rels_sys_module, rels_err_system, rels_sys_error, rels_err_class, rels_cla_error, rels_sys_server, rels_server, rels_server_module, rels_cla_son_cla, rels_son_cla_konw
# 建立节点

    def create_node(self, label, nodes):
            count = 0
            for node_name in nodes:
                node = Node(label, name=node_name)
                self.g.create(node)
                count += 1
            return

# 创建error、server、知识子类、知识节点

    def create_errors_nodes(self, error_infos):
            count = 0
            for error_dict in error_infos:
                node = Node("error", name=error_dict['name'], desc=error_dict['desc'], reason=error_dict['err_cause'],
                            err_effect=error_dict['err_effect'], check_way=error_dict['check_way'],
                            solve_way=error_dict['solve_way'])
                self.g.create(node)
                count += 1
            return
            # 创建服务器节点

    def create_servers_nodes(self, servers_infos):
            count = 0
            for server_dict in servers_infos:
                node = Node("server", name=server_dict['server'], ip_addr=server_dict['ip_addr'])
                self.g.create(node)
                count += 1
            return

            # 创建问题子类节点
            #	def create_son_cla_nodes(self, cla_son_infos):
            #		count = 0
            #		for son_cla_dict in cla_son_infos:
            #			node = Node("err_son_class", name=son_cla_dict['err_son_class'], cla_url=son_cla_dict['cla_url'])
            #			self.g.create(node)
            #			count += 1
            #		return

            # 创建子类知识点节点

    def create_konws_nodes(self, cla_son_know_infos):
            count = 0
            for know_dict in cla_son_know_infos:
                node = Node("know", name=know_dict['son_cla_know'], son_cla_url=know_dict['son_cla_url'],
                            know_desc=know_dict['know_desc'])
                self.g.create(node)
                count += 1
            return

            # 创建知识图谱实体节点类型schema

    def create_graphnodes(self):
            link_modules, servers, errors, systems, err_classes, err_son_classes, err_son_classes_knows, error_infos, servers_info, cla_son_infos, cla_son_know_infos, rels_link_module, rels_sys_module, rels_err_system, rels_sys_error, rels_err_class, rels_cla_error, rels_sys_server, rels_server, rels_server_module, rels_cla_son_cla, rels_son_cla_konw = self.read_nodes()
            self.create_errors_nodes(error_infos)
            self.create_servers_nodes(servers_info)
            #		self.create_son_cla_nodes(cla_son_infos)
            self.create_konws_nodes(cla_son_know_infos)
            self.create_node('link_module', link_modules)
            self.create_node('system', systems)
            self.create_node('err_class', err_classes)
            self.create_node('err_son_class', err_son_classes)
            return

            # 创建实体关系边

    def create_graphrels(self):
            link_modules, servers, errors, systems, err_classes, err_son_classes, err_son_classes_knows, error_infos, servers_info, cla_son_infos, cla_son_know_infos, rels_link_module, rels_sys_module, rels_err_system, rels_sys_error, rels_err_class, rels_cla_error, rels_sys_server, rels_server, rels_server_module, rels_cla_son_cla, rels_son_cla_konw = self.read_nodes()
            self.create_relationship('error', 'link_module', rels_link_module, 'rels_link_module', '问题-集群')
            self.create_relationship('system', 'link_module', rels_sys_module, 'rels_sys_module', '系统-集群')
            self.create_relationship('error', 'system', rels_err_system, 'rels_err_system', '问题-系统关系')
            self.create_relationship('system', 'error', rels_sys_error, 'rels_sys_error', '系统-问题关系')
            self.create_relationship('error', 'err_class', rels_err_class, 'rels_err_class', '问题-分类关系')
            self.create_relationship('err_class', 'error', rels_cla_error, 'rels_cla_error', '分类-问题关系')
            self.create_relationship('server', 'link_module', rels_server_module, 'rels_server_module', '集群-服务器关系')
            self.create_relationship('err_class', 'err_son_class', rels_cla_son_cla, 'rels_cla_son_cla', '知识大类-知识子类关系')
            self.create_relationship('err_son_class', 'know', rels_son_cla_konw, 'rels_son_cla_konw', '知识子类-子类知识点关系')
            # 创建实体关联边

    def create_relationship(self, start_node, end_node, edges, rel_type, rel_name):
            count = 0
            # 去重处理
            set_edges = []
            for edge in edges:
                set_edges.append('###'.join(edge))
            all = len(set(set_edges))
            for edge in set(set_edges):
                edge = edge.split('###')
                p = edge[0]
                q = edge[1]
                query = "match(p:%s),(q:%s) where p.name='%s'and q.name='%s' create (p)-[rel:%s{name:'%s'}]->(q)" % (
                    start_node, end_node, p, q, rel_type, rel_name)
                try:
                    self.g.run(query)
                    count += 1
                except Exception as e:
                    print(e)
                print(count)
                print(query)
            return
#导出数据
    def export_data(self):
        link_modules, servers, errors, systems, err_classes, err_son_classes, err_son_classes_knows, error_infos, servers_info, cla_son_infos, cla_son_know_infos, rels_link_module, rels_sys_module, rels_err_system, rels_sys_error, rels_err_class, rels_cla_error, rels_sys_server, rels_server, rels_server_module, rels_cla_son_cla, rels_son_cla_konw = self.read_nodes()
        f_link_module = open('/home/iotapp/OneCup/chatbot/data/link_module.txt', 'a+', encoding='utf-8')
        f_server = open('/home/iotapp/OneCup/chatbot/data/server.txt', 'a+', encoding='utf-8')
        f_error = open('/home/iotapp/OneCup/chatbot/data/error.txt', 'a+', encoding='utf-8')
        f_system = open('/home/iotapp/OneCup/chatbot/data/system.txt', 'a+', encoding='utf-8')
        f_class = open('/home/iotapp/OneCup/chatbot/data/class.txt', 'a+', encoding='utf-8')
        f_son_class = open('/home/iotapp/OneCup/chatbot/data/son_class.txt', 'a+', encoding='utf-8')
        f_son_class_know = open('/home/iotapp/OneCup/chatbot/data/son_class_know.txt', 'a+', encoding='utf-8')

        f_link_module.write('\n'.join(list(link_modules)))
        f_server.write('\n'.join(list(servers)))
        f_error.write('\n'.join(list(errors)))
        f_system.write('\n'.join(list(systems)))
        f_class.write('\n'.join(list(err_classes)))
        f_son_class.write('\n'.join(list(err_son_classes)))
        f_son_class_know.write('\n'.join(list(err_son_classes_knows)))

        f_link_module.close()
        f_server.close()
        f_error.close()
        f_system.close()
        f_class.close()
        f_son_class.close()
        f_son_class_know.close()
        return


    def export_dict(self):
        link_module = []
        with(open("/home/iotapp/OneCup/chatbot/data/link_module.txt", "r", encoding="utf-8")) as fr:
            vocablist = fr.readlines()
            for one in vocablist:
                if str(one).strip() != "":
                    temp = str(one).strip() + " " + str(15) + " nm" + "\n"
                    link_module.append(temp)
        with(open("/home/iotapp/OneCup/chatbot/data/userdict3.txt",
                "a+", encoding="utf-8")) as fw:
            for one in link_module:
                fw.write(one)
            fw.close()

        system = []
        with(open("/home/iotapp/OneCup/chatbot/data/system.txt", "r", encoding="utf-8")) as fr:
            vocablist = fr.readlines()
            for one in vocablist:
                if str(one).strip() != "":
                    temp = str(one).strip() + " " + str(15) + " sys" + "\n"
                    system.append(temp)
        with(open("/home/iotapp/OneCup/chatbot/data/userdict3.txt",
                "a+", encoding="utf-8")) as fw:
            for one in system:
                fw.write(one)
            fw.close()

        error = []
        with(open("/home/iotapp/OneCup/chatbot/data/error.txt", "r", encoding="utf-8")) as fr:
            vocablist = fr.readlines()
            for one in vocablist:
                if str(one).strip() != "":
                    temp = str(one).strip() + " " + str(15) + " er" + "\n"
                    error.append(temp)
        with(open("/home/iotapp/OneCup/chatbot/data/userdict3.txt",
                "a+", encoding="utf-8")) as fw:
            for one in error:
                fw.write(one)
            fw.close()

        classs = []
        with(open("/home/iotapp/OneCup/chatbot/data/class.txt", "r", encoding="utf-8")) as fr:
            vocablist = fr.readlines()
            for one in vocablist:
                if str(one).strip() != "":
                    temp = str(one).strip() + " " + str(15) + " kl" + "\n"
                    classs.append(temp)
        with(open("/home/iotapp/OneCup/chatbot/data/userdict3.txt",
                "a+", encoding="utf-8")) as fw:
            for one in classs:
                fw.write(one)
            fw.close()

        son_class = []
        with(open("/home/iotapp/OneCup/chatbot/data/son_class.txt", "r", encoding="utf-8")) as fr:
            vocablist = fr.readlines()
            for one in vocablist:
                if str(one).strip() != "":
                    temp = str(one).strip() + " " + str(15) + " ksl" + "\n"
                    son_class.append(temp)
        with(open("/home/iotapp/OneCup/chatbot/data/userdict3.txt",
                "a+", encoding="utf-8")) as fw:
            for one in son_class:
                fw.write(one)
            fw.close()

        son_class_know = []
        with(open("/home/iotapp/OneCup/chatbot/data/son_class_know.txt", "r", encoding="utf-8")) as fr:
            vocablist = fr.readlines()
            for one in vocablist:
                if str(one).strip() != "":
                    temp = str(one).strip() + " " + str(15) + " kn" + "\n"
                    son_class_know.append(temp)
        with(open("/home/iotapp/OneCup/chatbot/data/userdict3.txt",
                "a+", encoding="utf-8")) as fw:
            for one in son_class_know:
                fw.write(one)
            fw.close()
if __name__ == '__main__':
    handler = MedicalGraph()
    handler.create_graphnodes()
    handler.create_graphrels()
    handler.export_data()
    handler.export_dict()